# import tkinter as tk

# win = tk.Tk()
# win.title("九月四日")
# win.geometry('400x350+200+200')
# win.iconbitmap('icons8-卡尔·拉格菲尔德-32.ico')

# # 在主窗口上添加一个frame控件
# frame1 = tk.Frame(win)
# frame1.pack()

# # 在frame1上添加另外两个frame，一个在靠左，一个靠右
# # 左侧的frame
# frame_left = tk.Frame(frame1)
# tk.Label(frame_left, text='左侧标签1', bg='green', width=10, height=5).grid(row=0, column=0)
# tk.Label(frame_left, text='左侧标签2', bg='blue', width=10, height=5).grid(row=0, column=1)
# frame_left.pack(side=tk.LEFT)

# frame_right = tk.Frame(frame1)
# tk.Label(frame_right, text='右侧标签1', bg='gray', width=10, height=5).grid(row=0, column=1)
# tk.Label(frame_right, text='右侧标签2', bg='pink', width=10, height=5).grid(row=1, column=0)
# tk.Label(frame_right, text='右侧标签3', bg='purple', width=10, height=5).grid(row=1, column=1)
# tk.Label(frame_right, text='右侧标签4', bg='red', width=10, height=5).grid(row=0, column=0)
# frame_right.pack(side=tk.RIGHT)

# win.mainloop()


# from tkinter import *
# # 主窗口
# win = Tk()
# win.config(bg='#87CEEB')
# win.title("2025.9.4")
# win.geometry('800x600+300+300')
# win.iconbitmap('icons8-卡尔·拉格菲尔德-32.ico')

# # 在窗口内创建按钮，以表格的形式依次排列
# for i in range(9):
#     for j in range(9):
#         Button(win, text="(" + str(i) + "," + str(j) + ")", bg='#D1EEEE',width=5, height=2,).grid(row=i, column=j)

# # 在第5行第11列添加一个Label标签
# Label(win, text="yolo", fg='blue', font=('楷体', 10, 'bold')).grid(row=4, column=11)
# # 开始窗口的事件循环
# win.mainloop()


# from tkinter import *
# from tkinter import ttk

# # 主窗口
# win = Tk()
# win.config(bg='#87CEEB')
# win.title("2025.9.4")
# win.geometry('800x600+300+300')  # 初始窗口大小
# win.iconbitmap('icons8-卡尔·拉格菲尔德-32.ico')

# # 创建一个Canvas和Scrollbar以支持滚动
# canvas = Canvas(win)
# canvas.pack(side=LEFT, fill=BOTH, expand=True)

# scrollbar = ttk.Scrollbar(win, orient=VERTICAL, command=canvas.yview)
# scrollbar.pack(side=RIGHT, fill=Y)

# canvas.configure(yscrollcommand=scrollbar.set)

# # 创建一个Frame用于放置按钮
# frame = Frame(canvas)
# canvas.create_window((0, 0), window=frame, anchor="nw")

# # 在frame内创建按钮
# for i in range(36):
#     for j in range(36):
#         Button(frame, text="(" + str(i) + "," + str(j) + ")",
#                bg='#D1EEEE', width=5, height=1,
#                font=('Arial', 8), relief="groove").grid(row=i, column=j)

# # 在第5行第11列添加一个Label标签，调整字体大小
# Label(frame, text="yolo", fg='blue', font=('楷体', 7, 'bold')).grid(row=4, column=10)

# # 更新canvas的区域
# frame.update_idletasks()
# canvas.config(scrollregion=canvas.bbox("all"))

# # 开始窗口的事件循环
# win.mainloop()


# import tkinter as tk
# from tkinter import filedialog, messagebox
# import os
# from datetime import datetime

# class NoteApp:
#     def __init__(self, root):
#         self.root = root
#         self.root.title("记事本")
#         self.root.geometry("600x400")
#         self.current_file = None
#         self.unsaved_changes = False

#         # 创建菜单栏
#         self.create_menu()

#         # 创建文本框
#         self.text_area = tk.Text(self.root, wrap='word')
#         self.text_area.pack(expand='true', fill='both')
#         self.text_area.bind("<<Modified>>", self.on_text_change)

#     def create_menu(self):
#         menu_bar = tk.Menu(self.root)

#         # 文件菜单
#         file_menu = tk.Menu(menu_bar, tearoff=0)
        
#         # 新建子菜单
#         new_submenu = tk.Menu(file_menu, tearoff=0)
#         new_submenu.add_command(label="空白文档", command=self.new_note)
#         new_submenu.add_command(label="待办模板", command=self.new_todo_template)
#         new_submenu.add_command(label="日记模板", command=self.new_diary_template)
#         file_menu.add_cascade(label="新建模板", menu=new_submenu)
        
#         file_menu.add_command(label="打开", command=self.open_note)
#         file_menu.add_command(label="保存", command=self.save_note)
#         file_menu.add_command(label="另存为", command=self.save_as_note)
#         file_menu.add_separator()
#         file_menu.add_command(label="退出", command=self.exit_app)
#         menu_bar.add_cascade(label="文件", menu=file_menu)

#         self.root.config(menu=menu_bar)

#     def on_text_change(self, event=None):
#         if not self.unsaved_changes:
#             self.unsaved_changes = True
#             self.root.title(f"记事本 - *{self.current_file if self.current_file else '无标题'}")

#     def new_note(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
#         self.text_area.delete(1.0, tk.END)
#         self.current_file = None
#         self.unsaved_changes = False
#         self.root.title("记事本 - 新建")

#     def new_todo_template(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
        
#         self.text_area.delete(1.0, tk.END)
#         todo_template = """待办事项：

# 完成任务 A

# 完成任务 B

# 完成任务 C
# """
#         self.text_area.insert(tk.END, todo_template)
#         self.current_file = None
#         self.unsaved_changes = True
#         self.root.title("记事本 - 待办模板")

#     def new_diary_template(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
        
#         self.text_area.delete(1.0, tk.END)
#         today = datetime.today().strftime('%Y-%m-%d')
#         diary_template = f"""日记 - {today}：
# 今天做了什么？
# 遇到的问题：
# 今天的感悟：
# """
#         self.text_area.insert(tk.END, diary_template)
#         self.current_file = None
#         self.unsaved_changes = True
#         self.root.title("记事本 - 日记模板")

#     def open_note(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
#         file_path = filedialog.askopenfilename(defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("Markdown 文件", "*.md"), ("HTML 文件", "*.html")])
#         if file_path:
#             with open(file_path, 'r', encoding='utf-8') as file:
#                 content = file.read()
#                 self.text_area.delete(1.0, tk.END)
#                 self.text_area.insert(tk.END, content)
#                 self.current_file = file_path
#                 self.unsaved_changes = False
#                 self.root.title(f"记事本 - {os.path.basename(file_path)}")

#     def save_note(self):
#         if self.current_file:
#             with open(self.current_file, 'w', encoding='utf-8') as file:
#                 file.write(self.text_area.get(1.0, tk.END).strip())
#             self.unsaved_changes = False
#             self.root.title(f"记事本 - {os.path.basename(self.current_file)}")
#         else:
#             self.save_as_note()

#     def save_as_note(self):
#         file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("Markdown 文件", "*.md"), ("HTML 文件", "*.html")])
#         if file_path:
#             with open(file_path, 'w', encoding='utf-8') as file:
#                 file.write(self.text_area.get(1.0, tk.END).strip())
#             self.current_file = file_path
#             self.unsaved_changes = False
#             self.root.title(f"记事本 - {os.path.basename(file_path)}")

#     def exit_app(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
#         self.root.quit()

# if __name__ == "__main__":
#     root = tk.Tk()
#     app = NoteApp(root)
#     root.mainloop()


# import tkinter as tk
# from tkinter import filedialog, messagebox, font, colorchooser, simpledialog
# import os
# from datetime import datetime
# import re

# class NoteApp:
#     def __init__(self, root):
#         self.root = root
#         self.root.title("记事本")
#         self.root.geometry("800x500")
#         self.current_file = None
#         self.unsaved_changes = False
#         self.clipboard_history = []
#         self.max_clipboard_history = 10
#         self.undo_stack = []
#         self.redo_stack = []
#         self.max_undo_steps = 100
#         self.column_select_mode = False
#         self.find_dialog = None

#         # 创建菜单栏
#         self.create_menu()
        
#         # 创建工具栏
#         self.create_toolbar()

#         # 创建文本框
#         self.text_area = tk.Text(self.root, wrap='word', undo=True, maxundo=self.max_undo_steps)
#         self.text_area.pack(expand='true', fill='both', padx=5, pady=5)
#         self.text_area.bind("<<Modified>>", self.on_text_change)
#         self.text_area.bind("<Control-a>", self.select_all)
#         self.text_area.bind("<Control-A>", self.select_all)
#         self.text_area.bind("<Alt-ButtonPress-1>", self.start_column_select)
#         self.text_area.bind("<Alt-B1-Motion>", self.do_column_select)
#         self.text_area.bind("<Alt-ButtonRelease-1>", self.end_column_select)

#         # 配置标签
#         self.configure_tags()

#     def configure_tags(self):
#         # 配置文本格式标签
#         self.text_area.tag_configure("bold", font=("Arial", 10, "bold"))
#         self.text_area.tag_configure("italic", font=("Arial", 10, "italic"))
#         self.text_area.tag_configure("underline", underline=1)
#         self.text_area.tag_configure("strikethrough", overstrike=1)

#     def create_menu(self):
#         menu_bar = tk.Menu(self.root)

#         # 文件菜单
#         file_menu = tk.Menu(menu_bar, tearoff=0)
#         file_menu.add_command(label="新建", command=self.new_note)
        
#         # 新建子菜单
#         new_submenu = tk.Menu(file_menu, tearoff=0)
#         new_submenu.add_command(label="空白文档", command=self.new_note)
#         new_submenu.add_command(label="待办模板", command=self.new_todo_template)
#         new_submenu.add_command(label="日记模板", command=self.new_diary_template)
#         file_menu.add_cascade(label="新建模板", menu=new_submenu)
        
#         file_menu.add_command(label="打开", command=self.open_note)
#         file_menu.add_command(label="保存", command=self.save_note)
#         file_menu.add_command(label="另存为", command=self.save_as_note)
#         file_menu.add_separator()
#         file_menu.add_command(label="退出", command=self.exit_app)
#         menu_bar.add_cascade(label="文件", menu=file_menu)

#         # 编辑菜单
#         edit_menu = tk.Menu(menu_bar, tearoff=0)
#         edit_menu.add_command(label="撤销", command=self.undo, accelerator="Ctrl+Z")
#         edit_menu.add_command(label="重做", command=self.redo, accelerator="Ctrl+Y")
#         edit_menu.add_separator()
#         edit_menu.add_command(label="剪切", command=self.cut, accelerator="Ctrl+X")
#         edit_menu.add_command(label="复制", command=self.copy, accelerator="Ctrl+C")
#         edit_menu.add_command(label="粘贴", command=self.paste, accelerator="Ctrl+V")
#         edit_menu.add_command(label="粘贴历史", command=self.show_clipboard_history)
#         edit_menu.add_separator()
#         edit_menu.add_command(label="全选", command=self.select_all, accelerator="Ctrl+A")
#         edit_menu.add_command(label="列选模式", command=self.toggle_column_select)
#         menu_bar.add_cascade(label="编辑", menu=edit_menu)

#         # 查找菜单
#         find_menu = tk.Menu(menu_bar, tearoff=0)
#         find_menu.add_command(label="查找", command=self.find_text, accelerator="Ctrl+F")
#         find_menu.add_command(label="替换", command=self.replace_text, accelerator="Ctrl+H")
#         menu_bar.add_cascade(label="查找", menu=find_menu)

#         # 格式菜单
#         format_menu = tk.Menu(menu_bar, tearoff=0)
#         format_menu.add_command(label="粗体", command=self.apply_bold, accelerator="Ctrl+B")
#         format_menu.add_command(label="斜体", command=self.apply_italic, accelerator="Ctrl+I")
#         format_menu.add_command(label="下划线", command=self.apply_underline, accelerator="Ctrl+U")
#         format_menu.add_command(label="删除线", command=self.apply_strikethrough)
#         format_menu.add_separator()
#         format_menu.add_command(label="字体", command=self.choose_font)
#         format_menu.add_command(label="颜色", command=self.choose_color)
#         menu_bar.add_cascade(label="格式", menu=format_menu)

#         self.root.config(menu=menu_bar)

#     def create_toolbar(self):
#         toolbar = tk.Frame(self.root, bd=1, relief=tk.RAISED)
#         toolbar.pack(side=tk.TOP, fill=tk.X)

#         # 基础编辑按钮
#         tk.Button(toolbar, text="撤销", command=self.undo).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="重做", command=self.redo).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="剪切", command=self.cut).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="复制", command=self.copy).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="粘贴", command=self.paste).pack(side=tk.LEFT, padx=2, pady=2)

#         # 格式按钮
#         tk.Button(toolbar, text="B", command=self.apply_bold, font=("Arial", 10, "bold")).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="I", command=self.apply_italic, font=("Arial", 10, "italic")).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="U", command=self.apply_underline, font=("Arial", 10, "underline")).pack(side=tk.LEFT, padx=2, pady=2)
#         tk.Button(toolbar, text="S", command=self.apply_strikethrough).pack(side=tk.LEFT, padx=2, pady=2)

#         # 查找按钮
#         tk.Button(toolbar, text="查找", command=self.find_text).pack(side=tk.LEFT, padx=2, pady=2)

#     def on_text_change(self, event=None):
#         if not self.unsaved_changes:
#             self.unsaved_changes = True
#             self.root.title(f"记事本 - *{self.current_file if self.current_file else '无标题'}")

#     # 基础编辑功能
#     def undo(self):
#         try:
#             self.text_area.edit_undo()
#         except:
#             pass

#     def redo(self):
#         try:
#             self.text_area.edit_redo()
#         except:
#             pass

#     def cut(self):
#         selected_text = self.text_area.get(tk.SEL_FIRST, tk.SEL_LAST)
#         if selected_text:
#             self.root.clipboard_clear()
#             self.root.clipboard_append(selected_text)
#             self.add_to_clipboard_history(selected_text)
#             self.text_area.delete(tk.SEL_FIRST, tk.SEL_LAST)

#     def copy(self):
#         selected_text = self.text_area.get(tk.SEL_FIRST, tk.SEL_LAST)
#         if selected_text:
#             self.root.clipboard_clear()
#             self.root.clipboard_append(selected_text)
#             self.add_to_clipboard_history(selected_text)

#     def paste(self):
#         try:
#             clipboard_content = self.root.clipboard_get()
#             if clipboard_content:
#                 self.text_area.insert(tk.INSERT, clipboard_content)
#                 self.add_to_clipboard_history(clipboard_content)
#         except:
#             pass

#     def add_to_clipboard_history(self, text):
#         if text.strip():  # 只保存非空文本
#             self.clipboard_history.insert(0, text)
#             if len(self.clipboard_history) > self.max_clipboard_history:
#                 self.clipboard_history.pop()

#     def show_clipboard_history(self):
#         history_window = tk.Toplevel(self.root)
#         history_window.title("剪贴板历史")
#         history_window.geometry("400x300")
        
#         listbox = tk.Listbox(history_window)
#         listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
#         for i, item in enumerate(self.clipboard_history):
#             # 显示前50个字符
#             display_text = item[:50] + "..." if len(item) > 50 else item
#             listbox.insert(tk.END, f"{i+1}. {display_text}")
        
#         def paste_selected():
#             selection = listbox.curselection()
#             if selection:
#                 selected_text = self.clipboard_history[selection[0]]
#                 self.text_area.insert(tk.INSERT, selected_text)
#                 history_window.destroy()
        
#         button_frame = tk.Frame(history_window)
#         button_frame.pack(fill=tk.X, padx=5, pady=5)
        
#         tk.Button(button_frame, text="粘贴选中", command=paste_selected).pack(side=tk.LEFT)
#         tk.Button(button_frame, text="关闭", command=history_window.destroy).pack(side=tk.RIGHT)

#     def select_all(self, event=None):
#         self.text_area.tag_add(tk.SEL, "1.0", tk.END)
#         self.text_area.mark_set(tk.INSERT, "1.0")
#         self.text_area.see(tk.INSERT)
#         return "break"

#     def toggle_column_select(self):
#         self.column_select_mode = not self.column_select_mode
#         messagebox.showinfo("列选模式", f"列选模式 {'已启用' if self.column_select_mode else '已禁用'}")

#     def start_column_select(self, event):
#         if self.column_select_mode:
#             self.column_select_start = (event.x, event.y)
#             self.text_area.mark_set("column_anchor", f"@{event.x},{event.y}")

#     def do_column_select(self, event):
#         if self.column_select_mode and hasattr(self, 'column_select_start'):
#             self.text_area.tag_remove(tk.SEL, "1.0", tk.END)
#             start_index = self.text_area.index(f"@{self.column_select_start[0]},{self.column_select_start[1]}")
#             end_index = self.text_area.index(f"@{event.x},{event.y}")
            
#             # 简单的列选择实现
#             start_line, start_char = map(int, start_index.split('.'))
#             end_line, end_char = map(int, end_index.split('.'))
            
#             for line in range(min(start_line, end_line), max(start_line, end_line) + 1):
#                 line_start = f"{line}.{min(start_char, end_char)}"
#                 line_end = f"{line}.{max(start_char, end_char)}"
#                 self.text_area.tag_add(tk.SEL, line_start, line_end)

#     def end_column_select(self, event):
#         if self.column_select_mode:
#             self.column_select_mode = False

#     # 查找与替换功能
#     def find_text(self):
#         if self.find_dialog and self.find_dialog.winfo_exists():
#             self.find_dialog.lift()
#             return
            
#         self.find_dialog = tk.Toplevel(self.root)
#         self.find_dialog.title("查找")
#         self.find_dialog.geometry("300x150")
#         self.find_dialog.transient(self.root)
#         self.find_dialog.grab_set()
        
#         tk.Label(self.find_dialog, text="查找内容:").pack(pady=5)
#         find_entry = tk.Entry(self.find_dialog, width=30)
#         find_entry.pack(pady=5)
#         find_entry.focus()
        
#         case_var = tk.BooleanVar()
#         tk.Checkbutton(self.find_dialog, text="区分大小写", variable=case_var).pack()
        
#         def find_next():
#             text_to_find = find_entry.get()
#             if text_to_find:
#                 start_pos = self.text_area.index(tk.INSERT)
#                 content = self.text_area.get("1.0", tk.END)
#                 flags = 0 if case_var.get() else re.IGNORECASE
                
#                 # 从当前位置开始查找
#                 match = re.search(re.escape(text_to_find), content[int(self.text_area.index(tk.INSERT).split('.')[0]):], flags)
#                 if match:
#                     start_index = f"{int(start_pos.split('.')[0]) + match.start()}.0"
#                     end_index = f"{int(start_pos.split('.')[0]) + match.end()}.0"
#                     self.text_area.tag_remove(tk.SEL, "1.0", tk.END)
#                     self.text_area.tag_add(tk.SEL, start_index, end_index)
#                     self.text_area.mark_set(tk.INSERT, end_index)
#                     self.text_area.see(tk.INSERT)
#                 else:
#                     messagebox.showinfo("查找", "未找到匹配内容")
        
#         button_frame = tk.Frame(self.find_dialog)
#         button_frame.pack(pady=10)
        
#         tk.Button(button_frame, text="查找下一个", command=find_next).pack(side=tk.LEFT, padx=5)
#         tk.Button(button_frame, text="关闭", command=self.find_dialog.destroy).pack(side=tk.RIGHT, padx=5)

#     def replace_text(self):
#         replace_dialog = tk.Toplevel(self.root)
#         replace_dialog.title("替换")
#         replace_dialog.geometry("300x200")
#         replace_dialog.transient(self.root)
#         replace_dialog.grab_set()
        
#         tk.Label(replace_dialog, text="查找内容:").pack(pady=2)
#         find_entry = tk.Entry(replace_dialog, width=30)
#         find_entry.pack(pady=2)
        
#         tk.Label(replace_dialog, text="替换为:").pack(pady=2)
#         replace_entry = tk.Entry(replace_dialog, width=30)
#         replace_entry.pack(pady=2)
        
#         case_var = tk.BooleanVar()
#         tk.Checkbutton(replace_dialog, text="区分大小写", variable=case_var).pack()
        
#         def replace_all():
#             find_text = find_entry.get()
#             replace_text = replace_entry.get()
#             if find_text:
#                 content = self.text_area.get("1.0", tk.END)
#                 flags = 0 if case_var.get() else re.IGNORECASE
#                 new_content = re.sub(re.escape(find_text), replace_text, content, flags=flags)
#                 self.text_area.delete("1.0", tk.END)
#                 self.text_area.insert("1.0", new_content)
#                 self.unsaved_changes = True
        
#         button_frame = tk.Frame(replace_dialog)
#         button_frame.pack(pady=10)
        
#         tk.Button(button_frame, text="全部替换", command=replace_all).pack(side=tk.LEFT, padx=5)
#         tk.Button(button_frame, text="关闭", command=replace_dialog.destroy).pack(side=tk.RIGHT, padx=5)

#     # 格式调整功能
#     def apply_bold(self):
#         self.apply_tag("bold")

#     def apply_italic(self):
#         self.apply_tag("italic")

#     def apply_underline(self):
#         self.apply_tag("underline")

#     def apply_strikethrough(self):
#         self.apply_tag("strikethrough")

#     def apply_tag(self, tag_name):
#         try:
#             start = self.text_area.index(tk.SEL_FIRST)
#             end = self.text_area.index(tk.SEL_LAST)
#             self.text_area.tag_add(tag_name, start, end)
#         except:
#             pass

#     def choose_font(self):
#         font_window = tk.Toplevel(self.root)
#         font_window.title("选择字体")
#         font_window.geometry("300x200")
        
#         tk.Label(font_window, text="字体:").pack()
#         font_family = tk.StringVar(value="Arial")
#         font_list = tk.Listbox(font_window, height=6)
#         for f in font.families():
#             font_list.insert(tk.END, f)
#         font_list.pack(fill=tk.BOTH, expand=True)
        
#         tk.Label(font_window, text="大小:").pack()
#         size_var = tk.StringVar(value="12")
#         size_spin = tk.Spinbox(font_window, from_=8, to=72, textvariable=size_var)
#         size_spin.pack()
        
#         def apply_font():
#             selection = font_list.curselection()
#             if selection:
#                 family = font_list.get(selection[0])
#                 size = int(size_var.get())
#                 new_font = (family, size)
#                 self.text_area.configure(font=new_font)
#                 font_window.destroy()
        
#         tk.Button(font_window, text="应用", command=apply_font).pack(pady=10)

#     def choose_color(self):
#         color = colorchooser.askcolor(title="选择文本颜色")
#         if color[1]:
#             try:
#                 start = self.text_area.index(tk.SEL_FIRST)
#                 end = self.text_area.index(tk.SEL_LAST)
#                 tag_name = f"color_{color[1]}"
#                 self.text_area.tag_configure(tag_name, foreground=color[1])
#                 self.text_area.tag_add(tag_name, start, end)
#             except:
#                 pass

#     # 原有的文件操作功能保持不变
#     def new_note(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
#         self.text_area.delete(1.0, tk.END)
#         self.current_file = None
#         self.unsaved_changes = False
#         self.root.title("记事本 - 新建")

#     def new_todo_template(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
        
#         self.text_area.delete(1.0, tk.END)
#         todo_template = """待办事项：

# 完成任务 A

# 完成任务 B

# 完成任务 C
# """
#         self.text_area.insert(tk.END, todo_template)
#         self.current_file = None
#         self.unsaved_changes = True
#         self.root.title("记事本 - 待办模板")

#     def new_diary_template(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
        
#         self.text_area.delete(1.0, tk.END)
#         today = datetime.today().strftime('%Y-%m-%d')
#         diary_template = f"""日记 - {today}：
# 今天做了什么？
# 遇到的问题：
# 今天的感悟：
# """
#         self.text_area.insert(tk.END, diary_template)
#         self.current_file = None
#         self.unsaved_changes = True
#         self.root.title("记事本 - 日记模板")

#     def open_note(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
#         file_path = filedialog.askopenfilename(defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("Markdown 文件", "*.md"), ("HTML 文件", "*.html")])
#         if file_path:
#             with open(file_path, 'r', encoding='utf-8') as file:
#                 content = file.read()
#                 self.text_area.delete(1.0, tk.END)
#                 self.text_area.insert(tk.END, content)
#                 self.current_file = file_path
#                 self.unsaved_changes = False
#                 self.root.title(f"记事本 - {os.path.basename(file_path)}")

#     def save_note(self):
#         if self.current_file:
#             with open(self.current_file, 'w', encoding='utf-8') as file:
#                 file.write(self.text_area.get(1.0, tk.END).strip())
#             self.unsaved_changes = False
#             self.root.title(f"记事本 - {os.path.basename(self.current_file)}")
#         else:
#             self.save_as_note()

#     def save_as_note(self):
#         file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("Markdown 文件", "*.md"), ("HTML 文件", "*.html")])
#         if file_path:
#             with open(file_path, 'w', encoding='utf-8') as file:
#                 file.write(self.text_area.get(1.0, tk.END).strip())
#             self.current_file = file_path
#             self.unsaved_changes = False
#             self.root.title(f"记事本 - {os.path.basename(file_path)}")

#     def exit_app(self):
#         if self.unsaved_changes:
#             response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
#             if response:
#                 self.save_note()
#             elif response is None:
#                 return
#         self.root.quit()

# if __name__ == "__main__":
#     root = tk.Tk()
#     app = NoteApp(root)
#     root.mainloop()


import tkinter as tk
from tkinter import filedialog, messagebox, ttk, font
import os
from datetime import datetime
import re
from collections import deque

class EnhancedNoteApp:
    def __init__(self, root):
        self.root = root
        self.root.title("增强记事本")
        self.root.geometry("800x600")
        self.current_file = None
        self.unsaved_changes = False
        
        # 撤销/重做历史记录设置
        self.max_undo_steps = 100
        self.undo_stack = deque(maxlen=self.max_undo_steps)
        self.redo_stack = deque(maxlen=self.max_undo_steps)
        self.last_saved_state = None
        
        # 剪贴板历史
        self.clipboard_history = deque(maxlen=10)  # 保存最近10次剪贴内容
        
        # 列选模式标志
        self.column_select_mode = False
        
        # 创建字体和颜色配置
        self.default_font = font.Font(family="SimHei", size=12)
        self.current_font = self.default_font
        self.current_color = "black"
        self.current_tags = set()
        
        # 创建UI组件
        self.create_menu()
        self.create_toolbars()
        self.create_text_widget()
        self.create_status_bar()
        
        # 绑定事件
        self.bind_events()
        
        # 初始化撤销栈
        self.save_undo_state()

    def create_menu(self):
        # 创建主菜单栏
        menu_bar = tk.Menu(self.root)
        
        # 文件菜单
        file_menu = tk.Menu(menu_bar, tearoff=0)
        file_menu.add_command(label="新建", command=self.new_note, accelerator="Ctrl+N")
        new_submenu = tk.Menu(file_menu, tearoff=0)
        new_submenu.add_command(label="空白文档", command=self.new_note)
        new_submenu.add_command(label="待办模板", command=self.new_todo_template)
        new_submenu.add_command(label="日记模板", command=self.new_diary_template)
        file_menu.add_cascade(label="新建模板", menu=new_submenu)
        file_menu.add_command(label="打开", command=self.open_note, accelerator="Ctrl+O")
        file_menu.add_command(label="保存", command=self.save_note, accelerator="Ctrl+S")
        file_menu.add_command(label="另存为", command=self.save_as_note, accelerator="Ctrl+Shift+S")
        file_menu.add_separator()
        file_menu.add_command(label="退出", command=self.exit_app, accelerator="Ctrl+Q")
        menu_bar.add_cascade(label="文件", menu=file_menu)
        
        # 编辑菜单
        edit_menu = tk.Menu(menu_bar, tearoff=0)
        
        # 剪贴板操作
        edit_menu.add_command(label="撤销", command=self.undo, accelerator="Ctrl+Z")
        edit_menu.add_command(label="重做", command=self.redo, accelerator="Ctrl+Y")
        edit_menu.add_separator()
        edit_menu.add_command(label="剪切", command=self.cut, accelerator="Ctrl+X")
        edit_menu.add_command(label="复制", command=self.copy, accelerator="Ctrl+C")
        edit_menu.add_command(label="粘贴", command=self.paste, accelerator="Ctrl+V")
        
        # 剪贴板历史子菜单
        self.clipboard_history_menu = tk.Menu(edit_menu, tearoff=0)
        edit_menu.add_cascade(label="剪贴板历史", menu=self.clipboard_history_menu)
        
        edit_menu.add_separator()
        edit_menu.add_command(label="全选", command=self.select_all, accelerator="Ctrl+A")
        edit_menu.add_command(label="列选模式", command=self.toggle_column_select, accelerator="Alt+C")
        menu_bar.add_cascade(label="编辑", menu=edit_menu)
        
        # 查找替换菜单
        find_menu = tk.Menu(menu_bar, tearoff=0)
        find_menu.add_command(label="查找", command=self.open_find_dialog, accelerator="Ctrl+F")
        find_menu.add_command(label="替换", command=self.open_replace_dialog, accelerator="Ctrl+H")
        menu_bar.add_cascade(label="查找", menu=find_menu)
        
        # 格式菜单
        format_menu = tk.Menu(menu_bar, tearoff=0)
        
        # 字体子菜单
        font_menu = tk.Menu(format_menu, tearoff=0)
        self.font_var = tk.StringVar(value="SimHei")
        for f in font.families():
            font_menu.add_radiobutton(label=f, variable=self.font_var, command=self.change_font)
        format_menu.add_cascade(label="字体", menu=font_menu)
        
        # 字号子菜单
        size_menu = tk.Menu(format_menu, tearoff=0)
        self.size_var = tk.IntVar(value=12)
        for s in range(8, 25, 2):
            size_menu.add_radiobutton(label=str(s), variable=self.size_var, command=self.change_font_size)
        format_menu.add_cascade(label="字号", menu=size_menu)
        
        # 文本样式
        format_menu.add_separator()
        format_menu.add_command(label="粗体", command=self.toggle_bold, accelerator="Ctrl+B")
        format_menu.add_command(label="斜体", command=self.toggle_italic, accelerator="Ctrl+I")
        format_menu.add_command(label="下划线", command=self.toggle_underline, accelerator="Ctrl+U")
        format_menu.add_command(label="删除线", command=self.toggle_strikethrough)
        
        # 文本颜色
        format_menu.add_separator()
        format_menu.add_command(label="文本颜色", command=self.choose_text_color)
        
        menu_bar.add_cascade(label="格式", menu=format_menu)
        
        # 视图菜单
        view_menu = tk.Menu(menu_bar, tearoff=0)
        self.status_var = tk.BooleanVar(value=True)
        view_menu.add_checkbutton(label="状态栏", variable=self.status_var, command=self.toggle_status_bar)
        menu_bar.add_cascade(label="视图", menu=view_menu)
        
        # 帮助菜单
        help_menu = tk.Menu(menu_bar, tearoff=0)
        help_menu.add_command(label="关于", command=self.show_about)
        menu_bar.add_cascade(label="帮助", menu=help_menu)
        
        self.root.config(menu=menu_bar)

    def create_toolbars(self):
        # 创建主工具栏
        main_toolbar = ttk.Frame(self.root, padding="5")
        main_toolbar.pack(side=tk.TOP, fill=tk.X)
        
        # 编辑工具按钮
        ttk.Button(main_toolbar, text="撤销", command=self.undo).pack(side=tk.LEFT, padx=2)
        ttk.Button(main_toolbar, text="重做", command=self.redo).pack(side=tk.LEFT, padx=2)
        ttk.Separator(main_toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, padx=5, fill=tk.Y)
        
        ttk.Button(main_toolbar, text="剪切", command=self.cut).pack(side=tk.LEFT, padx=2)
        ttk.Button(main_toolbar, text="复制", command=self.copy).pack(side=tk.LEFT, padx=2)
        ttk.Button(main_toolbar, text="粘贴", command=self.paste).pack(side=tk.LEFT, padx=2)
        ttk.Separator(main_toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, padx=5, fill=tk.Y)
        
        ttk.Button(main_toolbar, text="查找", command=self.open_find_dialog).pack(side=tk.LEFT, padx=2)
        ttk.Button(main_toolbar, text="替换", command=self.open_replace_dialog).pack(side=tk.LEFT, padx=2)
        
        # 格式工具栏
        format_toolbar = ttk.Frame(self.root, padding="5")
        format_toolbar.pack(side=tk.TOP, fill=tk.X)
        
        ttk.Button(format_toolbar, text="B", command=self.toggle_bold, style="Bold.TButton").pack(side=tk.LEFT, padx=2)
        ttk.Button(format_toolbar, text="I", command=self.toggle_italic, style="Italic.TButton").pack(side=tk.LEFT, padx=2)
        ttk.Button(format_toolbar, text="U", command=self.toggle_underline, style="Underline.TButton").pack(side=tk.LEFT, padx=2)
        ttk.Button(format_toolbar, text="S", command=self.toggle_strikethrough, style="Strike.TButton").pack(side=tk.LEFT, padx=2)
        ttk.Separator(format_toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, padx=5, fill=tk.Y)
        
        ttk.Label(format_toolbar, text="字体:").pack(side=tk.LEFT, padx=2)
        ttk.Combobox(format_toolbar, textvariable=self.font_var, 
                    values=list(font.families()), width=12,
                    state="readonly").pack(side=tk.LEFT, padx=2)
        
        ttk.Label(format_toolbar, text="字号:").pack(side=tk.LEFT, padx=2)
        ttk.Combobox(format_toolbar, textvariable=self.size_var,
                    values=[str(s) for s in range(8, 25, 2)], width=5,
                    state="readonly").pack(side=tk.LEFT, padx=2)
        
        ttk.Button(format_toolbar, text="颜色", command=self.choose_text_color).pack(side=tk.LEFT, padx=2)
        
        # 自定义按钮样式
        ttk.Style().configure("Bold.TButton", font=(None, 10, "bold"))
        ttk.Style().configure("Italic.TButton", font=(None, 10, "italic"))
        ttk.Style().configure("Underline.TButton", font=(None, 10, "underline"))

    def create_text_widget(self):
        # 创建文本编辑区域
        text_frame = ttk.Frame(self.root)
        text_frame.pack(expand=True, fill=tk.BOTH, padx=5, pady=5)
        
        # 滚动条
        scroll_y = ttk.Scrollbar(text_frame, orient=tk.VERTICAL)
        scroll_x = ttk.Scrollbar(text_frame, orient=tk.HORIZONTAL)
        
        # 文本区域
        self.text_area = tk.Text(text_frame, wrap='word', undo=False,  # 禁用内置undo，使用自定义实现
                                yscrollcommand=scroll_y.set,
                                xscrollcommand=scroll_x.set,
                                font=self.default_font)
        
        scroll_y.config(command=self.text_area.yview)
        scroll_x.config(command=self.text_area.xview)
        
        # 网格布局
        self.text_area.grid(row=0, column=0, sticky=tk.NSEW)
        scroll_y.grid(row=0, column=1, sticky=tk.NS)
        scroll_x.grid(row=1, column=0, sticky=tk.EW)
        
        text_frame.grid_rowconfigure(0, weight=1)
        text_frame.grid_columnconfigure(0, weight=1)
        
        # 配置文本标签（用于格式化）
        self.text_area.tag_configure("bold", font=(self.default_font.actual("family"), 
                                                  self.default_font.actual("size"), "bold"))
        self.text_area.tag_configure("italic", font=(self.default_font.actual("family"), 
                                                   self.default_font.actual("size"), "italic"))
        self.text_area.tag_configure("underline", underline=True)
        self.text_area.tag_configure("strikethrough", overstrike=True)
        
        # 绑定文本变化事件
        self.text_area.bind("<<Modified>>", self.on_text_change)

    def create_status_bar(self):
        # 创建状态栏
        self.status_bar = ttk.Label(self.root, text="行: 1 | 列: 0", anchor=tk.W)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def bind_events(self):
        # 绑定快捷键
        self.root.bind("<Control-n>", lambda e: self.new_note())
        self.root.bind("<Control-o>", lambda e: self.open_note())
        self.root.bind("<Control-s>", lambda e: self.save_note())
        self.root.bind("<Control-Shift-S>", lambda e: self.save_as_note())
        self.root.bind("<Control-q>", lambda e: self.exit_app())
        self.root.bind("<Control-z>", lambda e: self.undo())
        self.root.bind("<Control-y>", lambda e: self.redo())
        self.root.bind("<Control-x>", lambda e: self.cut())
        self.root.bind("<Control-c>", lambda e: self.copy())
        self.root.bind("<Control-v>", lambda e: self.paste())
        self.root.bind("<Control-a>", lambda e: self.select_all())
        self.root.bind("<Control-f>", lambda e: self.open_find_dialog())
        self.root.bind("<Control-h>", lambda e: self.open_replace_dialog())
        self.root.bind("<Alt-c>", lambda e: self.toggle_column_select())
        self.root.bind("<Control-b>", lambda e: self.toggle_bold())
        self.root.bind("<Control-i>", lambda e: self.toggle_italic())
        self.root.bind("<Control-u>", lambda e: self.toggle_underline())
        
        # 绑定鼠标移动事件，更新状态栏
        self.text_area.bind("<Motion>", self.update_status)
        self.text_area.bind("<ButtonRelease-1>", self.update_status)
        
        # 绑定列选模式下的鼠标事件
        self.text_area.bind("<ButtonPress-1>", self.start_selection)

    def on_text_change(self, event=None):
        # 当文本内容改变时调用
        if self.text_area.edit_modified():
            self.save_undo_state()
            if not self.unsaved_changes:
                self.unsaved_changes = True
                self.root.title(f"增强记事本 - *{os.path.basename(self.current_file) if self.current_file else '无标题'}")
            self.text_area.edit_modified(False)

    def save_undo_state(self):
        # 保存当前状态到撤销栈
        state = self.text_area.get(1.0, tk.END)
        # 避免连续相同状态被多次保存
        if not self.undo_stack or state != self.undo_stack[-1]:
            self.undo_stack.append(state)
            # 每次新操作清空重做栈
            self.redo_stack.clear()

    def undo(self):
        if len(self.undo_stack) > 1:  # 至少保留一个初始状态
            # 将当前状态移到重做栈
            current_state = self.text_area.get(1.0, tk.END)
            self.redo_stack.append(current_state)
            
            # 从撤销栈恢复上一个状态
            self.undo_stack.pop()
            prev_state = self.undo_stack[-1]
            
            self.text_area.delete(1.0, tk.END)
            self.text_area.insert(1.0, prev_state)
            
            self.unsaved_changes = True
            self.update_status()

    def redo(self):
        if self.redo_stack:
            # 将当前状态移到撤销栈
            current_state = self.text_area.get(1.0, tk.END)
            self.undo_stack.append(current_state)
            
            # 从重做栈恢复下一个状态
            next_state = self.redo_stack.pop()
            
            self.text_area.delete(1.0, tk.END)
            self.text_area.insert(1.0, next_state)
            
            self.unsaved_changes = True
            self.update_status()

    def cut(self):
        # 剪切操作
        if self.text_area.tag_ranges("sel"):
            # 获取选中的文本
            selected_text = self.text_area.get(tk.SEL_FIRST, tk.SEL_LAST)
            # 添加到剪贴板历史
            self.clipboard_history.append(selected_text)
            self.update_clipboard_menu()
            # 执行剪切
            self.text_area.event_generate("<<Cut>>")
            self.unsaved_changes = True
            self.save_undo_state()

    def copy(self):
        # 复制操作
        if self.text_area.tag_ranges("sel"):
            # 获取选中的文本
            selected_text = self.text_area.get(tk.SEL_FIRST, tk.SEL_LAST)
            # 添加到剪贴板历史
            self.clipboard_history.append(selected_text)
            self.update_clipboard_menu()
            # 执行复制
            self.text_area.event_generate("<<Copy>>")

    def paste(self):
        # 粘贴操作
        self.text_area.event_generate("<<Paste>>")
        self.unsaved_changes = True
        self.save_undo_state()

    def update_clipboard_menu(self):
        # 更新剪贴板历史菜单
        # 先清空现有菜单
        for item in self.clipboard_history_menu.winfo_children():
            item.destroy()
        
        # 添加历史记录
        if not self.clipboard_history:
            self.clipboard_history_menu.add_command(label="无历史记录", state="disabled")
        else:
            for i, item in enumerate(reversed(self.clipboard_history)):
                # 限制显示长度
                display_text = item[:50] + "..." if len(item) > 50 else item
                # 移除换行符以便在菜单中更好地显示
                display_text = display_text.replace("\n", " ")
                self.clipboard_history_menu.add_command(
                    label=f"{i+1}: {display_text}",
                    command=lambda text=item: self.paste_from_history(text)
                )

    def paste_from_history(self, text):
        # 从历史记录粘贴
        self.text_area.insert(tk.INSERT, text)
        self.unsaved_changes = True
        self.save_undo_state()

    def select_all(self):
        # 全选
        self.text_area.tag_add("sel", "1.0", "end")

    def toggle_column_select(self):
        # 切换列选模式
        self.column_select_mode = not self.column_select_mode
        mode_text = "列选模式: 开启" if self.column_select_mode else "列选模式: 关闭"
        self.status_bar.config(text=mode_text)

    def start_selection(self, event):
        # 处理选择的开始，支持列选模式
        if self.column_select_mode:
            # 列选模式下的选择处理
            self.text_area.tag_remove("sel", "1.0", "end")
            self.col_start = self.text_area.index(f"@{event.x},{event.y}")
            self.text_area.mark_set("insert", self.col_start)
            # 绑定鼠标移动事件处理列选
            self.text_area.bind("<B1-Motion>", self.handle_column_select)
        else:
            # 普通选择模式
            self.text_area.bind("<B1-Motion>", None)

    def handle_column_select(self, event):
        # 处理列选
        self.text_area.tag_remove("sel", "1.0", "end")
        current_pos = self.text_area.index(f"@{event.x},{event.y}")
        
        # 解析起始和结束位置
        start_line, start_col = map(int, self.col_start.split('.'))
        end_line, end_col = map(int, current_pos.split('.'))
        
        # 确定列选范围
        min_line = min(start_line, end_line)
        max_line = max(start_line, end_line)
        min_col = min(start_col, end_col)
        max_col = max(start_col, end_col)
        
        # 选中指定范围内的列
        for line in range(min_line, max_line + 1):
            start = f"{line}.{min_col}"
            end = f"{line}.{max_col}"
            # 确保不超出行尾
            if self.text_area.compare(end, ">", f"{line}.end"):
                end = f"{line}.end"
            self.text_area.tag_add("sel", start, end)

    def update_status(self, event=None):
        # 更新状态栏显示行号和列号
        position = self.text_area.index(tk.INSERT)
        line, column = position.split('.')
        self.status_bar.config(text=f"行: {line} | 列: {column}")

    def toggle_status_bar(self):
        # 显示/隐藏状态栏
        if self.status_var.get():
            self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        else:
            self.status_bar.pack_forget()

    def open_find_dialog(self):
        # 创建查找对话框
        self.find_dialog = tk.Toplevel(self.root)
        self.find_dialog.title("查找")
        self.find_dialog.geometry("300x120")
        self.find_dialog.resizable(False, False)
        self.find_dialog.transient(self.root)
        self.find_dialog.grab_set()
        
        # 查找关键词
        ttk.Label(self.find_dialog, text="查找内容:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        self.find_entry = ttk.Entry(self.find_dialog, width=25)
        self.find_entry.grid(row=0, column=1, padx=5, pady=5)
        self.find_entry.focus_set()
        
        # 选项
        self.match_case = tk.BooleanVar()
        ttk.Checkbutton(self.find_dialog, text="匹配大小写", variable=self.match_case).grid(row=1, column=0, columnspan=2, sticky=tk.W, padx=5)
        
        # 按钮
        button_frame = ttk.Frame(self.find_dialog)
        button_frame.grid(row=2, column=0, columnspan=2, pady=10)
        
        ttk.Button(button_frame, text="查找下一个", command=self.find_next).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="查找上一个", command=self.find_previous).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="取消", command=self.find_dialog.destroy).pack(side=tk.LEFT, padx=5)

    def find_next(self):
        # 向下查找
        self.find_text(direction=1)

    def find_previous(self):
        # 向上查找
        self.find_text(direction=-1)

    def find_text(self, direction=1):
        # 查找文本实现
        search_text = self.find_entry.get()
        if not search_text:
            return
        
        # 获取当前位置
        current_pos = self.text_area.index(tk.INSERT)
        
        # 获取文本内容
        text_content = self.text_area.get("1.0", "end-1c")
        
        # 根据匹配大小写选项调整搜索
        if not self.match_case.get():
            text_to_search = text_content.lower()
            search_text_lower = search_text.lower()
        else:
            text_to_search = text_content
            search_text_lower = search_text
        
        # 计算当前位置在文本中的偏移量
        line, col = map(int, current_pos.split('.'))
        start_index = 0
        for i in range(1, line):
            start_index = self.text_area.count("1.0", current_pos, "chars")[0]
        start_index += col
        
        # 查找
        if direction == 1:
            pos = text_to_search.find(search_text_lower, start_index)
            if pos == start_index and len(search_text) > 0:
                pos = text_to_search.find(search_text_lower, start_index + 1)
        else:
            pos = text_to_search.rfind(search_text_lower, 0, start_index + len(search_text))
        
        if pos != -1:
            # 找到匹配项，计算对应的行列位置
            line_num = 1
            char_count = 0
            while line_num <= int(self.text_area.index('end').split('.')[0]):
                line_length = len(self.text_area.get(f"{line_num}.0", f"{line_num}.end")) + 1  # +1 是因为换行符
                if char_count + line_length > pos:
                    col_num = pos - char_count
                    break
                char_count += line_length
                line_num += 1
            
            # 取消之前的选择并选中找到的文本
            self.text_area.tag_remove("sel", "1.0", "end")
            start_pos = f"{line_num}.{col_num}"
            end_pos = f"{line_num}.{col_num + len(search_text)}"
            self.text_area.tag_add("sel", start_pos, end_pos)
            self.text_area.mark_set(tk.INSERT, end_pos)
            self.text_area.see(start_pos)
        else:
            messagebox.showinfo("查找", f"找不到 '{search_text}'")

    def open_replace_dialog(self):
        # 创建替换对话框
        self.replace_dialog = tk.Toplevel(self.root)
        self.replace_dialog.title("替换")
        self.replace_dialog.geometry("350x150")
        self.replace_dialog.resizable(False, False)
        self.replace_dialog.transient(self.root)
        self.replace_dialog.grab_set()
        
        # 查找关键词
        ttk.Label(self.replace_dialog, text="查找内容:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        self.replace_find_entry = ttk.Entry(self.replace_dialog, width=25)
        self.replace_find_entry.grid(row=0, column=1, padx=5, pady=5)
        self.replace_find_entry.focus_set()
        
        # 替换关键词
        ttk.Label(self.replace_dialog, text="替换为:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
        self.replace_with_entry = ttk.Entry(self.replace_dialog, width=25)
        self.replace_with_entry.grid(row=1, column=1, padx=5, pady=5)
        
        # 选项
        self.replace_match_case = tk.BooleanVar()
        ttk.Checkbutton(self.replace_dialog, text="匹配大小写", variable=self.replace_match_case).grid(row=2, column=0, columnspan=2, sticky=tk.W, padx=5)
        
        # 按钮
        button_frame = ttk.Frame(self.replace_dialog)
        button_frame.grid(row=3, column=0, columnspan=2, pady=10)
        
        ttk.Button(button_frame, text="查找下一个", command=self.replace_find_next).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="替换", command=self.replace_current).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="全部替换", command=self.replace_all).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="取消", command=self.replace_dialog.destroy).pack(side=tk.LEFT, padx=5)

    def replace_find_next(self):
        search_text = self.replace_find_entry.get()
        if not search_text:
            return
        # 设置查找参数
        self.match_case.set(self.replace_match_case.get())
        self.find_text(direction=1, search_text=search_text)

    # 修改 find_text 支持传入 search_text
    def find_text(self, direction=1, search_text=None):
        if search_text is None:
            search_text = self.find_entry.get()
        if not search_text:
            return

        # 获取当前插入点的字符偏移
        current_index = self.text_area.index(tk.INSERT)
        start_offset = self.text_area.count("1.0", current_index, "chars")[0]

        # 获取文本内容（去除末尾换行）
        full_text = self.text_area.get("1.0", "end-1c")

        # 大小写处理
        if not self.match_case.get():
            text_to_search = full_text.lower()
            search_text_lower = search_text.lower()
        else:
            text_to_search = full_text
            search_text_lower = search_text

        # 查找
        if direction == 1:  # 向下查找
            pos = text_to_search.find(search_text_lower, start_offset)
            if pos == start_offset and len(search_text) > 0:
                pos = text_to_search.find(search_text_lower, start_offset + 1)
        else:  # 向上查找
            pos = text_to_search.rfind(search_text_lower, 0, start_offset + len(search_text))

        if pos != -1:
            # 定位行号和列号
            line_num = 1
            char_count = 0
            while line_num <= int(self.text_area.index('end-1c').split('.')[0]):
                line_end = f"{line_num}.end"
                line_length = len(self.text_area.get(f"{line_num}.0", line_end)) + 1
                if char_count + line_length > pos:
                    col_num = pos - char_count
                    break
                char_count += line_length
                line_num += 1

            # 选中并滚动
            start_pos = f"{line_num}.{col_num}"
            end_pos = f"{line_num}.{col_num + len(search_text)}"
            self.text_area.tag_remove("sel", "1.0", "end")
            self.text_area.tag_add("sel", start_pos, end_pos)
            self.text_area.mark_set(tk.INSERT, end_pos)
            self.text_area.see(start_pos)
        else:
            messagebox.showinfo("查找", f"找不到 '{search_text}'")
    def replace_current(self):
        # 替换当前选中的文本
        search_text = self.replace_find_entry.get()
        replace_text = self.replace_with_entry.get()
        
        if not search_text or not self.text_area.tag_ranges("sel"):
            return
            
        # 检查选中的文本是否与查找文本匹配
        selected_text = self.text_area.get(tk.SEL_FIRST, tk.SEL_LAST)
        if (self.replace_match_case.get() and selected_text == search_text) or \
           (not self.replace_match_case.get() and selected_text.lower() == search_text.lower()):
            # 替换文本
            self.text_area.delete(tk.SEL_FIRST, tk.SEL_LAST)
            self.text_area.insert(tk.SEL_FIRST, replace_text)
            self.unsaved_changes = True
            self.save_undo_state()
            
            # 继续查找下一个
            self.replace_find_next()

    def replace_all(self):
        # 替换所有匹配项
        search_text = self.replace_find_entry.get()
        replace_text = self.replace_with_entry.get()
        
        if not search_text:
            return
            
        # 获取所有文本
        text_content = self.text_area.get(1.0, tk.END)
        
        # 执行替换
        if self.replace_match_case.get():
            new_content = text_content.replace(search_text, replace_text)
        else:
            # 不区分大小写的替换需要更复杂的处理
            new_content = re.sub(re.escape(search_text), replace_text, text_content, 
                                flags=re.IGNORECASE)
        
        # 更新文本区域
        self.text_area.delete(1.0, tk.END)
        self.text_area.insert(1.0, new_content)
        
        self.unsaved_changes = True
        self.save_undo_state()
        messagebox.showinfo("替换", "替换完成")

    def change_font(self):
        # 更改字体
        family = self.font_var.get()
        size = self.size_var.get()
        
        # 保留当前的字体样式
        weight = "bold" if "bold" in self.current_tags else "normal"
        slant = "italic" if "italic" in self.current_tags else "roman"
        
        self.current_font = font.Font(family=family, size=size, weight=weight, slant=slant)
        self.text_area.configure(font=self.current_font)
        
        # 更新标签配置
        self.text_area.tag_configure("bold", font=(family, size, "bold"))
        self.text_area.tag_configure("italic", font=(family, size, "italic"))

    def change_font_size(self):
        # 更改字号
        self.change_font()  # 调用change_font，因为它已经处理了字号变更

    def toggle_bold(self):
        # 切换粗体
        self.toggle_text_style("bold")

    def toggle_italic(self):
        # 切换斜体
        self.toggle_text_style("italic")

    def toggle_underline(self):
        # 切换下划线
        self.toggle_text_style("underline")

    def toggle_strikethrough(self):
        # 切换删除线
        self.toggle_text_style("strikethrough")

    def toggle_text_style(self, style):
        # 切换文本样式的通用方法
        if self.text_area.tag_ranges("sel"):
            # 有选中的文本，应用样式到选中区域
            start, end = self.text_area.tag_ranges("sel")
            
            if self.text_area.tag_nextrange(style, start, end):
                # 移除样式
                self.text_area.tag_remove(style, start, end)
                if style in self.current_tags:
                    self.current_tags.remove(style)
            else:
                # 添加样式
                self.text_area.tag_add(style, start, end)
                self.current_tags.add(style)
            
            self.unsaved_changes = True
            self.save_undo_state()
        else:
            # 没有选中文本，更新当前样式状态
            if style in self.current_tags:
                self.current_tags.remove(style)
            else:
                self.current_tags.add(style)
            
            # 更新当前字体
            self.change_font()

    def choose_text_color(self):
        # 选择文本颜色
        from tkinter import colorchooser
        color = colorchooser.askcolor(title="选择文本颜色")[1]
        if color:
            self.current_color = color
            if self.text_area.tag_ranges("sel"):
                start, end = self.text_area.tag_ranges("sel")
                # 创建或配置颜色标签
                if f"color_{color}" not in self.text_area.tag_names():
                    self.text_area.tag_configure(f"color_{color}", foreground=color)
                self.text_area.tag_add(f"color_{color}", start, end)
                self.unsaved_changes = True
                self.save_undo_state()

    def new_note(self):
        if self.unsaved_changes:
            response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
            if response:
                self.save_note()
            elif response is None:
                return
        self.text_area.delete(1.0, tk.END)
        self.current_file = None
        self.unsaved_changes = False
        self.root.title("增强记事本 - 新建")
        # 重置撤销栈
        self.undo_stack.clear()
        self.redo_stack.clear()
        self.save_undo_state()

    def new_todo_template(self):
        if self.unsaved_changes:
            response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
            if response:
                self.save_note()
            elif response is None:
                return
        
        self.text_area.delete(1.0, tk.END)
        todo_template = """待办事项：

• 完成任务 A

• 完成任务 B

• 完成任务 C

----------------------------------------
已完成：

• 
"""
        self.text_area.insert(tk.END, todo_template)
        self.current_file = None
        self.unsaved_changes = True
        self.root.title("增强记事本 - 待办模板")
        # 重置撤销栈
        self.undo_stack.clear()
        self.redo_stack.clear()
        self.save_undo_state()

    def new_diary_template(self):
        if self.unsaved_changes:
            response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
            if response:
                self.save_note()
            elif response is None:
                return
        
        self.text_area.delete(1.0, tk.END)
        today = datetime.today().strftime('%Y-%m-%d')
        weekday = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"][datetime.today().weekday()]
        diary_template = f"""日记 - {today} ({weekday})

天气：

今日总结：

遇到的问题与解决方案：

明日计划：

感悟与思考：
"""
        self.text_area.insert(tk.END, diary_template)
        self.current_file = None
        self.unsaved_changes = True
        self.root.title("增强记事本 - 日记模板")
        # 重置撤销栈
        self.undo_stack.clear()
        self.redo_stack.clear()
        self.save_undo_state()

    def open_note(self):
        if self.unsaved_changes:
            response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
            if response:
                self.save_note()
            elif response is None:
                return
        file_path = filedialog.askopenfilename(
            defaultextension=".txt", 
            filetypes=[
                ("文本文件", "*.txt"), 
                ("Markdown 文件", "*.md"), 
                ("HTML 文件", "*.html"),
                ("所有文件", "*.*")
            ]
        )
        if file_path:
            try:
                with open(file_path, 'r', encoding='utf-8') as file:
                    content = file.read()
                    self.text_area.delete(1.0, tk.END)
                    self.text_area.insert(tk.END, content)
                    self.current_file = file_path
                    self.unsaved_changes = False
                    self.root.title(f"增强记事本 - {os.path.basename(file_path)}")
                    # 重置撤销栈
                    self.undo_stack.clear()
                    self.redo_stack.clear()
                    self.save_undo_state()
            except Exception as e:
                messagebox.showerror("错误", f"无法打开文件: {str(e)}")

    def save_note(self):
        if self.current_file:
            try:
                with open(self.current_file, 'w', encoding='utf-8') as file:
                    content = self.text_area.get(1.0, tk.END)
                    file.write(content)
                self.unsaved_changes = False
                self.root.title(f"增强记事本 - {os.path.basename(self.current_file)}")
                return True
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {str(e)}")
                return False
        else:
            return self.save_as_note()

    def save_as_note(self):
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt", 
            filetypes=[
                ("文本文件", "*.txt"), 
                ("Markdown 文件", "*.md"), 
                ("HTML 文件", "*.html"),
                ("所有文件", "*.*")
            ]
        )
        if file_path:
            self.current_file = file_path
            return self.save_note()
        return False

    def exit_app(self):
        if self.unsaved_changes:
            response = messagebox.askyesnocancel("未保存的更改", "是否保存当前笔记?")
            if response:
                if not self.save_note():
                    return  # 如果保存失败，不退出
            elif response is None:
                return
        self.root.quit()

    def show_about(self):
        messagebox.showinfo(
            "关于", 
            "增强记事本 v1.0\n\n一个功能丰富的文本编辑工具，支持多种编辑模式和格式设置。"
        )

if __name__ == "__main__":
    root = tk.Tk()
    app = EnhancedNoteApp(root)
    root.mainloop()
